﻿/******************************************************************************
 * Copyright (C) 671643387@qq.com
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 *****************************************************************************/

#ifndef GAME_WORLD_WORLD_H_
#define GAME_WORLD_WORLD_H_

#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif

#include <ctime>
#include <list>
#include <boost/unordered_map.hpp>
#include <NodeCpp/Macros.h>
#include <NodeCpp/Singleton.h>
#include <NodeCpp/ThreadingModel.h>
#include <NodeCpp/Mutex.h>
#include <NodeCpp/LockedQueue.h>
#include "Shared/Typedef.h"
#include "Shared/Common.h"
#include "World/WorldDefines.h"
using NodeCpp::Singleton;
using NodeCpp::ClassLevelLockable;
using NodeCpp::SingleThreadMutex;
using NodeCpp::Mutex;
using NodeCpp::LockedQueue;

class WorldSocketDelegate;
class WorldSession;

class World
{
public:
    World(void);
    ~World(void);

    /* 初始化游戏世界变量 */
    void InitializeVars(const struct Configuration::Any& _WorldConf);
    /* 加载DBC文件 */
    bool LoadDBCs(const struct Configuration::Any& _WorldConf);
    /* 初始化游戏世界 */
    bool InitializeWorld(const struct Configuration::Any& _WorldConf);
    /* 更新游戏世界 */
    void Update(time_t _Diff);
    /* 关闭游戏世界 */
    void Close(void);

    bool IsRunning(void) const { return Running_; }
    void AddSession(WorldSession* _Session) { NewSessions_.Add(_Session); }
    WorldSession* FindSession(std::uint32_t _AccountId);
    /* 获取总会话数量（不包含新创建的会话） */
    std::uint32_t GetActiveAndQueuedSessionCount(void) const { return Sessions_.size(); }
    /* 获取游戏世界中的会话数量 */
    std::uint32_t GetActiveSessionCount(void) const { return Sessions_.size() - QueuedSessions_.size(); }
    /* 获取正在排队的会话数量 */
    std::uint32_t GetQueuedSessionCount(void) const { return QueuedSessions_.size(); }

    /******************** 游戏世界配置 ********************/
    std::uint32_t GetConfig(ConfigUInt32Values _Index) { return ConfigUInt32_[_Index]; }
    float GetConfig(ConfigFloatValues _Index) { return ConfigFloat_[_Index]; }
    void SetConfig(ConfigUInt32Values _Index, std::uint32_t _Value) { ConfigUInt32_[_Index] = _Value; }
    void SetConfig(ConfigFloatValues _Index, float _Value) { ConfigFloat_[_Index] = _Value; }

private:
    /* 更新会话 */
    void _UpdateSessions(void);
    void _AddSession(WorldSession* _Session);
    void _AddQueuedSession(WorldSession* _Session);
    bool _RemoveQueuedSession(WorldSession* _Session);
    std::uint32_t _GetQueuedSessionPos(WorldSession* _Session);
    /* 更新服务器热度 */
    void _UpdatePopulation(void);

    typedef LockedQueue<WorldSession*> NewSessionQueue;
    typedef std::list<WorldSession*> SessionQeueu;
    typedef boost::unordered_map<int, WorldSession*> SessionMap;

    // 新创建的会话，等待加入会话表
    NewSessionQueue NewSessions_;
    // 正在排队的会话，等待进入游戏世界
    SessionQeueu QueuedSessions_;
    // 会话表，包含已经进入游戏世界的会话和正在排队的会话
    SessionMap Sessions_;
    // 游戏世界是否在运行
    bool Running_;

    // 配置数据
    std::uint32_t ConfigUInt32_[CONFIG_UINT32_VALUE_COUNT];
    float ConfigFloat_[CONFIG_FLOAT_VALUE_COUNT];

    DISALLOW_COPY_AND_ASSIGN(World);
};
#define sWorld NodeCpp::Singleton<World>::Instance()

#endif // GAME_WORLD_WORLD_H_
